/**
 * @Author: easten
 * @Created: 2024-07-17 15:14:43
 * @Description: 请求工具类
 *
 */

import axios, { AxiosResponse, InternalAxiosRequestConfig } from "axios";
import { getStorage, removeStorage, setStorage } from "./StorageUtil";
import { MessagePlugin } from "tdesign-react";
import host from "configs/host";

const SUCCESS_CODE = 200;

export enum TokenEnum {
  //请求的token
  ACCESS_TOKEN_KEY = "access-token",
  //刷新的token
  REFRESH_TOKEN_KEY = "x-access-token",
  //TokenName
  TOKEN_NAME = "Authorization",
  // Token前缀，注意最后有个空格，如不需要需设置空字符串 // Bearer
  TOKEN_PREFIX = "Bearer ",
}

export const tokenKey = "tokenKey";
export const refreshTokenKey = "refreshTokenKey";

const decryptJWT = (token: string) => {
  token = token.replace(/_/g, "/").replace(/-/g, "+");
  const json = decodeURIComponent(escape(window.atob(token.split(".")[1])));
  return JSON.parse(json);
};

const getJWTDate = (timestamp: number) => {
  return new Date(timestamp * 1000);
};

// 检查存储的token信息
const checkAndStoreAuthentication = (res: AxiosResponse) => {
  // 读取响应报文头 token 信息
  let accessToken = res.headers[TokenEnum.ACCESS_TOKEN_KEY];
  let refreshAccessToken = res.headers[TokenEnum.REFRESH_TOKEN_KEY];
  // 判断是否是无效 token
  if (accessToken === "invalid_token") {
    removeStorage(tokenKey);
    removeStorage(refreshTokenKey);
  }
  // 判断是否存在刷新 token，如果存在则存储在本地
  else if (
    refreshAccessToken &&
    accessToken &&
    accessToken !== "invalid_token"
  ) {
    setStorage(tokenKey, accessToken);
    setStorage(refreshTokenKey, refreshAccessToken);
  }
};

/**
 * 请求拦截器
 * @param value 请求配置
 * @returns 拦截器
 */
const requestInterceptor = (
  value: InternalAxiosRequestConfig
): InternalAxiosRequestConfig => {
  const token = getStorage(tokenKey);
  const refreshToken = getStorage(refreshTokenKey);
  if (token && value && value.headers) {
    value.headers[TokenEnum.TOKEN_NAME] = `${TokenEnum.TOKEN_PREFIX}${token}`;
    // 判断token是否过期
    let jwt = decryptJWT(token);
    const exp = getJWTDate(jwt.exp);
    if (new Date() >= exp) {
      // 过期了
      const refreshAccessToken = refreshToken;
      // 携带刷新 token
      if (refreshAccessToken) {
        //value.headers.set?('X-' + TokenEnum.TOKEN_NAME, TokenEnum.TOKEN_PREFIX + refreshAccessToken);
        value.headers.set(
          "X-" + TokenEnum.TOKEN_NAME,
          TokenEnum.TOKEN_PREFIX + refreshAccessToken
        );
      }
    }
  }
  if (value.method === "get") {
    value.params = {
      ...value.params,
      _t: new Date().getTime(),
    };
  }
  return value;
};

const env = import.meta.env.MODE || "development";
const url = env == "development" ? host.development.API : host.test.API;

const axiosDefault = axios.create({
  timeout: 30000,
  baseURL: url,
});

axiosDefault.interceptors.request.use(requestInterceptor);
axiosDefault.interceptors.response.use(
  (response) => {
    // 判断更新
    checkAndStoreAuthentication(response);
    // 判断是否登录成功
    if (response) {
      if (response.data.code === 401) {
        // 未登录
        removeStorage(tokenKey);
        removeStorage(refreshTokenKey);
        return Promise.reject(response.data);
      }
      // 全局信息拦截
      if (response.data.code != 200) {
        // 服务器错误
        MessagePlugin.error(response.data.msg);
        return Promise.reject(response.data);
      } else {
        const { data } = response;
        if (data.code === SUCCESS_CODE) {
          return data;
        }
        return Promise.reject(data);
      }
    }
  },
  (e) => Promise.reject(e)
);

export default axiosDefault;
